package br.com.tcc.dao;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;
import javax.persistence.Query;

import org.apache.log4j.Logger;

import br.com.tcc.model.Categoria;

public class CategoriaDAO {
	private EntityManagerFactory emf;
	
	Logger logger = Logger.getLogger(CategoriaDAO.class);
	
	public CategoriaDAO() {
		emf = Persistence.createEntityManagerFactory("persistencia");
	}
	
	public boolean adicionar(Categoria categoria) {
		EntityManager em = emf.createEntityManager();
		boolean retorno = true;
		try{
			em.getTransaction().begin();
			em.merge(categoria);
			em.getTransaction().commit();
		}catch(Exception e){
			em.getTransaction().rollback();
			 logger.warn("Erro no metodo  [ " + e.getMessage() + " ]");
			retorno = false;
		}finally{
			em.close();
		}
	   	return retorno;
	}
	/**
	 * Buscar uma categoria pelo nome
	 * @return
	 */
	public Categoria buscar(String nome) {
		Categoria retorno = null;
		EntityManager em = emf.createEntityManager();
		try{
		   	em.getTransaction().begin();
		   	Query q = em.createQuery("select c from Categoria c where c.nome=:nome");
		   	q.setParameter("nome", nome);
		   	retorno = (Categoria) q.getSingleResult();
	   	
		}catch (NoResultException e) {
			logger.info("sem registro");
		}catch (Exception e) {
			 logger.warn("Erro no metodo  [ " + e.getMessage() + " ]");
		}finally{
			em.close();
		}
		
		return retorno;
	}
	/**
	 * obter a lista de produtos na base
	 * @return
	 */

	public void remover(Categoria c) {
		EntityManager em = emf.createEntityManager();
		
		try{
		   	em.getTransaction().begin();
		   	Query q = em.createQuery("delete from Categoria c where c.idCategoria = :idCategoria");
		 	q.setParameter("idCategoria", c.getIdCategoria());
		   	q.executeUpdate();
		 	em.getTransaction().commit();
		}catch (NoResultException e) {
			logger.info("sem registro");
		}catch (Exception e) {
			 logger.warn("Erro no metodo  [ " + e.getMessage() + " ]");
		}finally{
			em.close();
		}
		
	}

	public Categoria buscarId(int id){
		Categoria retorno = null;
		EntityManager em = emf.createEntityManager();
		try{
		   	em.getTransaction().begin();
		   	retorno = em.find(Categoria.class, id);
		}catch (NoResultException e) {
			logger.info("sem registro");
		}catch (Exception e) {
			 logger.warn("Erro no metodo  [ " + e.getMessage() + " ]");
		}finally{
			em.close();
		}
		return retorno;
	}

	public void atualizar(Categoria c){
		EntityManager em = emf.createEntityManager();
		try{
		   	em.getTransaction().begin();
		   	em.merge(c);
		   	em.getTransaction().commit();
		}catch(Exception e){
			em.getTransaction().rollback();
			 logger.warn("Erro no metodo  [ " + e.getMessage() + " ]");
		}finally{
			em.close();
		}
	}

	public Categoria buscarNomeCategoriaPai(String nome, int categoriaPai) {
		Categoria retorno = null;
		EntityManager em = emf.createEntityManager();
		try{
		   	em.getTransaction().begin();
		   	Query q = em.createQuery("select c from Categoria c where c.nome=:nome and c.categoriaPai = :categoriaPai");
		   	q.setParameter("nome", nome);
		   	q.setParameter("categoriaPai", categoriaPai);
		   	retorno = (Categoria) q.getSingleResult();
	   	
		}catch (NoResultException e) {
			logger.info("sem registro");
		}catch (Exception e) {
			 logger.warn("Erro no metodo  [ " + e.getMessage() + " ]");
		}finally{
			em.close();
		}
		
		return retorno;
	}

	public List<Categoria> buscarCategorias() {
		List<Categoria> retorno = null;
		EntityManager em = emf.createEntityManager();
		try{
		   	em.getTransaction().begin();
		   	Query q = em.createQuery("select c from Categoria c where c.nivelCategoria = 0 order by c.nome");
		   	retorno = q.getResultList();
		   	//Buscar as categorias filhas de nivel 1
		   	for (int i = 0; i < retorno.size(); i++) {
		   		List<Categoria> lCategorias1 = new ArrayList<Categoria>();
		   		q = em.createQuery("select c from Categoria c where c.nivelCategoria=1 and c.categoriaPai = :categoriaPai order by c.nome");
		   		q.setParameter("categoriaPai", retorno.get(i).getIdCategoria());
		   		lCategorias1 = q.getResultList();
		   		retorno.get(i).setCategoriasFilhas(lCategorias1);
		   	//Buscar as categorias filhas de nivel 2	
		   		for (int j = 0; j < lCategorias1.size(); j++) {
			   		List<Categoria> lCategorias2 = new ArrayList<Categoria>();
			   		q = em.createQuery("select c from Categoria c where c.nivelCategoria=2 and c.categoriaPai = :categoriaPai order by c.nome");
			   		q.setParameter("categoriaPai", lCategorias1.get(j).getIdCategoria());
			   		lCategorias2 = q.getResultList();
			   		lCategorias1.get(j).setCategoriasFilhas(lCategorias2);
			   	//Buscar as categorias filhas de nivel 3
			   		for (int k = 0; k < lCategorias2.size(); k++) {
			   			List<Categoria> lCategorias3 = new ArrayList<Categoria>();
				   		q = em.createQuery("select c from Categoria c where c.nivelCategoria=3 and c.categoriaPai = :categoriaPai order by c.nome");
				   		q.setParameter("categoriaPai", lCategorias2.get(k).getIdCategoria());
				   		lCategorias3 = q.getResultList();
				   		lCategorias2.get(k).setCategoriasFilhas(lCategorias3);
					}
				}
			}
		}catch (NoResultException e) {
			logger.info("sem registro");
		}catch (Exception e) {
			 logger.warn("Erro no metodo  [ " + e.getMessage() + " ]");
		}finally{
			em.close();
		}
		
		return retorno;
	}

	public List<Categoria> buscarCategoriaPorNivel(int nivelCategoria) {
		List<Categoria> retorno = null;
		EntityManager em = emf.createEntityManager();
		try{
		   	em.getTransaction().begin();
		   	Query q = em.createQuery("select c from Categoria c where c.nivelCategoria = :nivelCategoria order by c.nome");
		   	q.setParameter("nivelCategoria", nivelCategoria);
		   	retorno = q.getResultList();
	   	
		}catch (NoResultException e) {
			logger.info("sem registro");
		}catch (Exception e) {
			 logger.warn("Erro no metodo  [ " + e.getMessage() + " ]");
		}finally{
			em.close();
		}
		return retorno;
	}
	
	/**
	 * Buscar as categorias pelo nivel e pelo id do pai
	 * @param nivelCategoria
	 * @param categoriaPai
	 * @return
	 */
	public List<Categoria> buscarCategoriaPorNivelePai(int nivelCategoria, int categoriaPai) {
		List<Categoria> retorno = null;
		EntityManager em = emf.createEntityManager();
		try{
		   	em.getTransaction().begin();
		   	Query q = em.createQuery("select c from Categoria c where c.nivelCategoria=:nivelCategoria and c.categoriaPai = :categoriaPai");
		   	q.setParameter("nivelCategoria", nivelCategoria);
		   	q.setParameter("categoriaPai", categoriaPai);
		   	retorno =  q.getResultList();
	   	
		}catch (NoResultException e) {
			logger.info("sem registro");
		}catch (Exception e) {
			 logger.warn("Erro no metodo  [ " + e.getMessage() + " ]");
		}finally{
			em.close();
		}
		
		return retorno;
	}

	/**
	 * Buscar as todas as categorias cadastradas no site
	 * @param nivelCategoria
	 * @param categoriaPai
	 * @return
	 */
	public List<Categoria> listarCategorias() {
		List<Categoria> retorno = null;
		EntityManager em = emf.createEntityManager();
		try{
		   	em.getTransaction().begin();
		   	Query q = em.createQuery("select c from Categoria c order by c.nome");
		   	retorno =  q.getResultList();
	   	
		}catch (NoResultException e) {
			logger.info("sem registro");
		}catch (Exception e) {
			 logger.warn("Erro no metodo  [ " + e.getMessage() + " ]");
		}finally{
			em.close();
		}
		
		return retorno;
	}
	
}
